/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cronos.agent;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author leoomoreira
 */
public class CronosMonitor extends Thread {

    private long time;
    private Connection catalogConnection;

    /**
     * Construtor of the Agent Notifier
     *
     * @param time - Time used to establish a delay
     * @param catalogConnection -
     * @throws SQLException
     */
    public CronosMonitor(long time, Connection catalogConnection) throws SQLException {
        this.time = time;
        this.catalogConnection = catalogConnection;
    }

    /**
     * Lifecycle agent
     */
    @Override
    public void run() {
        OutputMessage.println("CronosMonitor: " + "is running");
        while (catalogConnection != null) {
            // Delay - Begin
            long currentTime = System.currentTimeMillis();
            long nextTime = currentTime + time;
            while (currentTime <= nextTime) {
                currentTime = System.currentTimeMillis();
            }
            // Delay - End
            try {
                Statement statement = catalogConnection.createStatement();
                long memoryTotal = ShellCommand.getMemoryTotal();
                long diskTotal = ShellCommand.getDiskTotal();
                double cpuFree = ShellCommand.getCPUFreePercentage();
                long memoryFree = ShellCommand.getMemoryFree();
                long diskFree = ShellCommand.getDiskFree();

                List<Integer> applicationsId = getApplicationsId();
                for (Integer applicationId : applicationsId) {
                    List<Integer> metricsId = getMetricsByApplicationId(applicationId);
                    for (Integer metricId : metricsId) {
                        switch (metricId) {
                            case 1: {
                                statement.executeUpdate(getApplicationMetricValueInsertSQL(applicationId, metricId, cpuFree));
                                break;
                            }
                            case 2: {
                                statement.executeUpdate(getApplicationMetricValueInsertSQL(applicationId, metricId, memoryFree));
                                break;
                            }
                            case 3: {
                                statement.executeUpdate(getApplicationMetricValueInsertSQL(applicationId, metricId, diskFree));
                                break;
                            }
                        }
                    }
                }
                statement.close();
            } catch (SQLException ex) {
            }
        }
        try {
            catalogConnection.close();
        } catch (SQLException ex) {
            catalogConnection = null;
        }
    }

    private String getApplicationMetricValueInsertSQL(int applicationId, int metricId, double value) {
        String sql = "";
        sql += "INSERT INTO application_metric_value (\"time\", application_id, metric_id, value) VALUES ";
        sql += "(now(), " + applicationId + ", " + metricId + ", " + value + ")";
        return sql;
    }

    private List<Integer> getApplicationsId() throws SQLException {
        List<Integer> result = new ArrayList<Integer>();
        PreparedStatement preparedStatement = catalogConnection.prepareStatement("SELECT id FROM application");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            result.add(resultSet.getInt("id"));
        }
        resultSet.close();
        preparedStatement.close();
        return result;
    }

    private List<Integer> getMetricsByApplicationId(int applicationId) throws SQLException {
        List<Integer> result = new ArrayList<Integer>();
        PreparedStatement preparedStatement = catalogConnection.prepareStatement("SELECT metric_id FROM application_metric WHERE application_id = ?");
        preparedStatement.setInt(1, applicationId);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            result.add(resultSet.getInt("metric_id"));
        }
        resultSet.close();
        preparedStatement.close();
        return result;
    }

}
